add api of user signup/login

Brightcells 9 years ago
parent
commit
3454610bb7

+ 20 - 2
account/admin.py

@@ -3,14 +3,14 @@
3 3
 from django.contrib import admin
4 4
 from django.contrib.auth.hashers import make_password
5 5
 
6
-from account.models import LensmanInfo
6
+from account.models import LensmanInfo, LensmanLoginLogInfo, UserInfo, UserLoginLogInfo
7 7
 
8 8
 from utils.uuid_utils import curtailUUID
9 9
 
10 10
 
11 11
 class LensmanInfoAdmin(admin.ModelAdmin):
12 12
     readonly_fields = ('lensman_id', 'encryption', )
13
-    list_display = ('lensman_id', 'name', 'sex', 'phone', 'location', 'proportion', 'status', 'created_at', 'updated_at')
13
+    list_display = ('lensman_id', 'username', 'name', 'sex', 'phone', 'location', 'proportion', 'status', 'created_at', 'updated_at')
14 14
     search_fields = ('name', 'phone', 'location')
15 15
     list_filter = ('sex', 'status')
16 16
 
@@ -23,4 +23,22 @@ class LensmanInfoAdmin(admin.ModelAdmin):
23 23
         obj.save()
24 24
 
25 25
 
26
+class LensmanLoginLogInfoAdmin(admin.ModelAdmin):
27
+    list_display = ('lensman_id', 'login_ip', 'login_result', 'status', 'created_at', 'updated_at')
28
+
29
+
30
+class UserInfoAdmin(admin.ModelAdmin):
31
+    readonly_fields = ('user_id', )
32
+    list_display = ('user_id', 'username', 'name', 'sex', 'phone', 'location', 'user_status', 'status', 'created_at', 'updated_at')
33
+    search_fields = ('name', 'phone', 'location')
34
+    list_filter = ('sex', 'status', 'user_status')
35
+
36
+
37
+class UserLoginLogInfoAdmin(admin.ModelAdmin):
38
+    list_display = ('user_id', 'login_ip', 'login_result', 'status', 'created_at', 'updated_at')
39
+
40
+
26 41
 admin.site.register(LensmanInfo, LensmanInfoAdmin)
42
+admin.site.register(UserInfo, UserInfoAdmin)
43
+admin.site.register(LensmanLoginLogInfo, LensmanLoginLogInfoAdmin)
44
+admin.site.register(UserLoginLogInfo, UserLoginLogInfoAdmin)

+ 85 - 0
account/migrations/0005_auto_20151209_1638.py

@@ -0,0 +1,85 @@
1
+# -*- coding: utf-8 -*-
2
+from __future__ import unicode_literals
3
+
4
+from django.db import models, migrations
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('account', '0004_auto_20151207_1811'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.CreateModel(
15
+            name='LensmanLoginLogInfo',
16
+            fields=[
17
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
18
+                ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')),
19
+                ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
20
+                ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
21
+                ('lensman_id', models.CharField(max_length=255, blank=True, help_text='\u6444\u5f71\u5e08\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='lensman_id', db_index=True)),
22
+                ('login_ip', models.CharField(help_text='\u767b\u5f55IP', max_length=255, null=True, verbose_name='login_ip', blank=True)),
23
+                ('login_result', models.IntegerField(default=0, verbose_name='login_result', choices=[(0, '\u767b\u5f55\u6210\u529f'), (1, '\u5bc6\u7801\u9519\u8bef'), (2, '\u5176\u4ed6')])),
24
+            ],
25
+            options={
26
+                'verbose_name': 'lensmanloginloginfo',
27
+                'verbose_name_plural': 'lensmanloginloginfo',
28
+            },
29
+        ),
30
+        migrations.CreateModel(
31
+            name='UserInfo',
32
+            fields=[
33
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
34
+                ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')),
35
+                ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
36
+                ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
37
+                ('user_id', models.CharField(null=True, max_length=255, blank=True, help_text='\u7528\u6237\u552f\u4e00\u6807\u8bc6', unique=True, verbose_name='user_id', db_index=True)),
38
+                ('username', models.CharField(null=True, max_length=255, blank=True, help_text='\u7528\u6237\u7528\u6237\u540d', unique=True, verbose_name='username', db_index=True)),
39
+                ('password', models.CharField(help_text='\u7528\u6237\u5bc6\u7801', max_length=255, null=True, verbose_name='password', blank=True)),
40
+                ('name', models.CharField(help_text='\u7528\u6237\u59d3\u540d', max_length=255, null=True, verbose_name='name', blank=True)),
41
+                ('sex', models.IntegerField(default=0, help_text='\u7528\u6237\u6027\u522b', verbose_name='sex', choices=[(0, '\u7537'), (1, '\u5973')])),
42
+                ('phone', models.CharField(null=True, max_length=255, blank=True, help_text='\u7528\u6237\u7535\u8bdd', unique=True, verbose_name='phone', db_index=True)),
43
+                ('location', models.CharField(help_text='\u7528\u6237\u5730\u5740', max_length=255, null=True, verbose_name='location', blank=True)),
44
+                ('user_status', models.IntegerField(default=0, verbose_name='user_status', choices=[(0, '\u672a\u9a8c\u8bc1'), (1, '\u5df2\u6fc0\u6d3b'), (2, '\u5df2\u7981\u7528'), (3, '\u5df2\u5220\u9664')])),
45
+                ('signup_ip', models.CharField(help_text='\u6ce8\u518cIP', max_length=255, null=True, verbose_name='signup_ip', blank=True)),
46
+                ('login_ip', models.CharField(help_text='\u767b\u5f55IP', max_length=255, null=True, verbose_name='login_ip', blank=True)),
47
+                ('login_at', models.DateTimeField(help_text='\u767b\u5f55\u65f6\u95f4', null=True, verbose_name='login_at', blank=True)),
48
+            ],
49
+            options={
50
+                'verbose_name': 'userinfo',
51
+                'verbose_name_plural': 'userinfo',
52
+            },
53
+        ),
54
+        migrations.CreateModel(
55
+            name='UserLoginLogInfo',
56
+            fields=[
57
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
58
+                ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')),
59
+                ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
60
+                ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
61
+                ('user_id', models.CharField(max_length=255, blank=True, help_text='\u7528\u6237\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='user_id', db_index=True)),
62
+                ('login_ip', models.CharField(help_text='\u767b\u5f55IP', max_length=255, null=True, verbose_name='login_ip', blank=True)),
63
+                ('login_result', models.IntegerField(default=0, verbose_name='login_result', choices=[(0, '\u767b\u5f55\u6210\u529f'), (1, '\u5bc6\u7801\u9519\u8bef'), (2, '\u5176\u4ed6')])),
64
+            ],
65
+            options={
66
+                'verbose_name': 'userloginloginfo',
67
+                'verbose_name_plural': 'userloginloginfo',
68
+            },
69
+        ),
70
+        migrations.AddField(
71
+            model_name='lensmaninfo',
72
+            name='login_at',
73
+            field=models.DateTimeField(help_text='\u767b\u5f55\u65f6\u95f4', null=True, verbose_name='login_at', blank=True),
74
+        ),
75
+        migrations.AddField(
76
+            model_name='lensmaninfo',
77
+            name='login_ip',
78
+            field=models.CharField(help_text='\u767b\u5f55IP', max_length=255, null=True, verbose_name='login_ip', blank=True),
79
+        ),
80
+        migrations.AddField(
81
+            model_name='lensmaninfo',
82
+            name='signup_ip',
83
+            field=models.CharField(help_text='\u6ce8\u518cIP', max_length=255, null=True, verbose_name='signup_ip', blank=True),
84
+        ),
85
+    ]

+ 103 - 0
account/models.py

@@ -28,9 +28,112 @@ class LensmanInfo(CreateUpdateMixin):
28 28
 
29 29
     proportion = models.FloatField(_(u'proportion'), default=1.0, help_text=u'摄影师分成比例(0.0 ~ 1.0)')
30 30
 
31
+    signup_ip = models.CharField(_(u'signup_ip'), max_length=255, blank=True, null=True, help_text=_(u'注册IP'))
32
+    login_ip = models.CharField(_(u'login_ip'), max_length=255, blank=True, null=True, help_text=_(u'登录IP'))
33
+    login_at = models.DateTimeField(_(u'login_at'), blank=True, null=True, help_text=_(u'登录时间'))
34
+
31 35
     class Meta:
32 36
         verbose_name = _(u'lensmaninfo')
33 37
         verbose_name_plural = _(u'lensmaninfo')
34 38
 
35 39
     def __unicode__(self):
36 40
         return unicode(self.pk)
41
+
42
+
43
+class LensmanLoginLogInfo(CreateUpdateMixin):
44
+    SUCCESS = 0
45
+    PWD_ERROR = 1
46
+    OTHER = 2
47
+
48
+    LOGIN_RESULT = (
49
+        (SUCCESS, u'登录成功'),
50
+        (PWD_ERROR, u'密码错误'),
51
+        (OTHER, u'其他'),
52
+    )
53
+
54
+    lensman_id = models.CharField(_(u'lensman_id'), max_length=255, blank=True, null=True, help_text=u'摄影师唯一标识', db_index=True)
55
+    login_ip = models.CharField(_(u'login_ip'), max_length=255, blank=True, null=True, help_text=_(u'登录IP'))
56
+    login_result = models.IntegerField(_(u'login_result'), choices=LOGIN_RESULT, default=SUCCESS)
57
+
58
+    class Meta:
59
+        verbose_name = _(u'lensmanloginloginfo')
60
+        verbose_name_plural = _(u'lensmanloginloginfo')
61
+
62
+    def __unicode__(self):
63
+        return unicode(self.pk)
64
+
65
+
66
+class UserInfo(CreateUpdateMixin):
67
+    UNVERIFIED = 0
68
+    ACTIVATED = 1
69
+    DISABLED = 2
70
+    DELETED = 3
71
+
72
+    USER_STATUS = (
73
+        (UNVERIFIED, u'未验证'),
74
+        (ACTIVATED, u'已激活'),
75
+        (DISABLED, u'已禁用'),
76
+        (DELETED, u'已删除'),
77
+    )
78
+
79
+    MALE = 0
80
+    FEMALE = 1
81
+
82
+    SEX_TYPE = (
83
+        (MALE, u'男'),
84
+        (FEMALE, u'女'),
85
+    )
86
+
87
+    user_id = models.CharField(_(u'user_id'), max_length=255, blank=True, null=True, help_text=u'用户唯一标识', db_index=True, unique=True)
88
+
89
+    username = models.CharField(_(u'username'), max_length=255, blank=True, null=True, help_text=u'用户用户名', db_index=True, unique=True)
90
+    password = models.CharField(_(u'password'), max_length=255, blank=True, null=True, help_text=u'用户密码')
91
+
92
+    name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'用户姓名')
93
+    sex = models.IntegerField(_(u'sex'), choices=SEX_TYPE, default=MALE, help_text=u'用户性别')
94
+    phone = models.CharField(_(u'phone'), max_length=255, blank=True, null=True, help_text=u'用户电话', db_index=True, unique=True)
95
+    location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'用户地址')
96
+
97
+    user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED)
98
+
99
+    signup_ip = models.CharField(_(u'signup_ip'), max_length=255, blank=True, null=True, help_text=_(u'注册IP'))
100
+    login_ip = models.CharField(_(u'login_ip'), max_length=255, blank=True, null=True, help_text=_(u'登录IP'))
101
+    login_at = models.DateTimeField(_(u'login_at'), blank=True, null=True, help_text=_(u'登录时间'))
102
+
103
+    class Meta:
104
+        verbose_name = _(u'userinfo')
105
+        verbose_name_plural = _(u'userinfo')
106
+
107
+    def __unicode__(self):
108
+        return unicode(self.pk)
109
+
110
+    def _data(self):
111
+        return {
112
+            'user_id': self.user_id,
113
+            'username': self.username,
114
+        }
115
+
116
+    data = property(_data)
117
+
118
+
119
+class UserLoginLogInfo(CreateUpdateMixin):
120
+    SUCCESS = 0
121
+    PWD_ERROR = 1
122
+    OTHER = 2
123
+
124
+    LOGIN_RESULT = (
125
+        (SUCCESS, u'登录成功'),
126
+        (PWD_ERROR, u'密码错误'),
127
+        (OTHER, u'其他'),
128
+    )
129
+
130
+    user_id = models.CharField(_(u'user_id'), max_length=255, blank=True, null=True, help_text=u'用户唯一标识', db_index=True)
131
+    login_ip = models.CharField(_(u'login_ip'), max_length=255, blank=True, null=True, help_text=_(u'登录IP'))
132
+    login_result = models.IntegerField(_(u'login_result'), choices=LOGIN_RESULT, default=SUCCESS)
133
+
134
+    class Meta:
135
+        verbose_name = _(u'userloginloginfo')
136
+        verbose_name_plural = _(u'userloginloginfo')
137
+
138
+    def __unicode__(self):
139
+        return unicode(self.pk)

+ 7 - 1
account/serializers.py

@@ -3,7 +3,7 @@
3 3
 from django.contrib.auth.models import User, Group
4 4
 from rest_framework import serializers
5 5
 
6
-from account.models import LensmanInfo
6
+from account.models import LensmanInfo, UserInfo
7 7
 
8 8
 
9 9
 class UserSerializer(serializers.HyperlinkedModelSerializer):
@@ -22,3 +22,9 @@ class LensmanInfoSerializer(serializers.HyperlinkedModelSerializer):
22 22
     class Meta:
23 23
         model = LensmanInfo
24 24
         fields = ('lensman_id', 'name', 'sex', 'phone', 'location', 'proportion', 'created_at')
25
+
26
+
27
+class UserInfoSerializer(serializers.HyperlinkedModelSerializer):
28
+    class Meta:
29
+        model = UserInfo
30
+        fields = ('user_id', 'name', 'sex', 'phone', 'location', 'user_status', 'created_at')

+ 92 - 4
account/views.py

@@ -1,17 +1,22 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 
3
-from django.contrib.auth.hashers import check_password
3
+from django.contrib.auth.hashers import make_password, check_password
4 4
 from django.contrib.auth.models import User, Group
5 5
 from django.http import JsonResponse
6 6
 
7 7
 from rest_framework import viewsets
8 8
 
9
-from account.models import LensmanInfo
10
-from account.serializers import UserSerializer, GroupSerializer, LensmanInfoSerializer
9
+from account.models import LensmanInfo, UserInfo, UserLoginLogInfo
10
+from account.serializers import UserSerializer, GroupSerializer, LensmanInfoSerializer, UserInfoSerializer
11
+
12
+from utils.ip_utils import ip_addr
13
+from utils.uuid_utils import curtailUUID
14
+
15
+from TimeConvert import TimeConvert as tc
11 16
 
12 17
 
13 18
 # curl -X POST -F username=xxxxxxx -F password=xxxxxxx http://api.xfoto.com.cn/login
14
-def user_login(request):
19
+def lesman_login_api(request):
15 20
     username = request.POST.get('username', '')
16 21
     password = request.POST.get('password', '')
17 22
 
@@ -38,6 +43,84 @@ def user_login(request):
38 43
     })
39 44
 
40 45
 
46
+def user_is_registered_api(request):
47
+    username = request.POST.get('username', '')
48
+    return JsonResponse({
49
+        'status': 200,
50
+        'message': '',
51
+        'data': {
52
+            'registered': UserInfo.objects.filter(username=username).exists(),
53
+        }
54
+    })
55
+
56
+
57
+def user_signup_api(request):
58
+    username = request.POST.get('username', '')
59
+    password = request.POST.get('password', '')
60
+
61
+    if UserInfo.objects.filter(username=username).exists():
62
+        return JsonResponse({
63
+            'status': 4010,
64
+            'message': u'该用户名已注册',
65
+        })
66
+
67
+    user = UserInfo.objects.create(
68
+        user_id=curtailUUID(UserInfo, 'user_id'),
69
+        username=username,
70
+        password=make_password(password, None, 'pbkdf2_sha256'),
71
+        user_status=UserInfo.ACTIVATED,
72
+        signup_ip=ip_addr(request),
73
+    )
74
+
75
+    return JsonResponse({
76
+        'status': 200,
77
+        'message': u'注册成功',
78
+        'data': user.data,
79
+    })
80
+
81
+
82
+def user_login_api(request):
83
+    username = request.POST.get('username', '')
84
+    password = request.POST.get('password', '')
85
+
86
+    try:
87
+        user = UserInfo.objects.get(username=username)
88
+    except UserInfo.DoesNotExist:
89
+        return JsonResponse({
90
+            'status': 4011,
91
+            'message': u'用户不存在',
92
+        })
93
+
94
+    login_ip, login_at = ip_addr(request), tc.utc_datetime()
95
+
96
+    if not check_password(password, user.password):
97
+        UserLoginLogInfo.objects.create(
98
+            user_id=user.user_id,
99
+            login_ip=login_ip,
100
+            login_result=UserLoginLogInfo.PWD_ERROR
101
+        )
102
+        return JsonResponse({
103
+            'status': 4012,
104
+            'message': u'用户密码错误',
105
+        })
106
+
107
+    UserLoginLogInfo.objects.create(
108
+        user_id=user.user_id,
109
+        login_ip=login_ip,
110
+        login_result=UserLoginLogInfo.SUCCESS
111
+    )
112
+
113
+    user.login_ip = login_ip
114
+    user.login_at = login_at
115
+    user.save()
116
+
117
+    return JsonResponse({
118
+        'status': 200,
119
+        'message': u'登录成功',
120
+        'data': user.data,
121
+    })
122
+
123
+
41 124
 class UserViewSet(viewsets.ModelViewSet):
42 125
     """
43 126
     API endpoint that allows users to be viewed or edited.
@@ -57,3 +140,8 @@ class GroupViewSet(viewsets.ModelViewSet):
57 140
 class LensmanInfoViewSet(viewsets.ModelViewSet):
58 141
     queryset = LensmanInfo.objects.all().order_by('-created_at')
59 142
     serializer_class = LensmanInfoSerializer
143
+
144
+
145
+class UserInfoViewSet(viewsets.ModelViewSet):
146
+    queryset = UserInfo.objects.all().order_by('-created_at')
147
+    serializer_class = UserInfoSerializer

+ 8 - 5
api/urls.py

@@ -7,16 +7,19 @@ from photo import views as photo_views
7 7
 
8 8
 
9 9
 urlpatterns = [
10
-    url(r'^login$', account_views.user_login, name='user_login'),
10
+    url(r'^login$', account_views.lesman_login_api, name='lesman_login_api'),
11
+    url(r'^u/is_registered$', account_views.user_is_registered_api, name='user_is_registered_api'),  # 用户是否已经注册
12
+    url(r'^u/signup$', account_views.user_signup_api, name='user_signup_api'),  # 用户注册
13
+    url(r'^u/login$', account_views.user_login_api, name='user_login_api'),  # 用户登录
11 14
 ]
12 15
 
13 16
 urlpatterns += [
14
-    url(r'^uuid_init$', photo_views.uuid_init, name='uuid_init'),
15
-    url(r'^uuid$', photo_views.uuid, name='uuid'),
16
-    url(r'^photos/upload$', photo_views.upload_photo, name='upload_photo'),
17
+    url(r'^uuid_init$', photo_views.uuid_init, name='uuid_init'),  # 生成唯一标识
18
+    url(r'^uuid$', photo_views.uuid, name='uuid'),  # 获取唯一标识
19
+    url(r'^photos/upload$', photo_views.upload_photo, name='upload_photo'),  # 上传图片
17 20
 ]
18 21
 
19 22
 urlpatterns += [
20
-    url(r'^s/(?P<session>\w+)$', photo_views.session_detail_api, name='session_detail_api'),
23
+    url(r'^s/(?P<session>\w+)$', photo_views.session_detail_api, name='session_detail_api'),  # Session 详情
21 24
     url(r'^p/(?P<photo>\w+)$', photo_views.photo_standard_api, name='photo_standard_api'),  # standard thumbnail, available for free
22 25
 ]

+ 6 - 2
docs/errorcode

@@ -1,6 +1,10 @@
1 1
 1、用户信息 —— 400
2
-    4000 —— 用户不存在
3
-    4001 —— 用户密码错误
2
+    4000 —— 摄影师不存在
3
+    4001 —— 摄影师密码错误
4
+
5
+    4010 —— 用户名已注册
6
+    4011 —— 用户名不存在
7
+    4012 —— 用户密码错误
4 8
 
5 9
 2、照片上传 —— 401
6 10
     4010 —— 参数错误

+ 4 - 1
pai2/urls.py

@@ -1,3 +1,5 @@
1
+# -*- coding: utf-8 -*-
2
+
1 3
 """pai2 URL Configuration
2 4
 
3 5
 The `urlpatterns` list routes URLs to views. For more information please see:
@@ -26,6 +28,7 @@ router = routers.DefaultRouter()
26 28
 # router.register(r'users', account_views.UserViewSet)
27 29
 # router.register(r'groups', account_views.GroupViewSet)
28 30
 router.register(r'lensmans', account_views.LensmanInfoViewSet)
31
+router.register(r'users', account_views.UserInfoViewSet)
29 32
 router.register(r'photos', photo_views.PhotoInfoViewSet)
30 33
 
31 34
 urlpatterns = [
@@ -34,7 +37,7 @@ urlpatterns = [
34 37
 
35 38
 urlpatterns += [
36 39
     # url(r'^api/', include('api.urls', namespace='api')),
37
-    url(r'^s/(?P<session>\w+)$', photo_views.session_detail, name='session_detail'),
40
+    url(r'^s/(?P<session>\w+)$', photo_views.session_detail, name='session_detail'),  # Session 详情
38 41
     url(r'^p/(?P<photo>\w+)$', photo_views.photo_standard, name='photo_standard'),  # standard thumbnail, available for free
39 42
     url(r'^m/(?P<photo>\w+)$', photo_views.photo_medium, name='photo_medium'),  # medium/mobile version, without watermark, login or paid by others
40 43
     url(r'^l/(?P<photo>\w+)$', photo_views.photo_large, name='photo_large'),  # large, might support server side panning later, login required

+ 0 - 1
pai2/urls_api.py

@@ -1,6 +1,5 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 
3
-
4 3
 from django.conf import settings
5 4
 from django.conf.urls import include, url
6 5
 

+ 1 - 1
requirements.txt

@@ -1,7 +1,7 @@
1 1
 CodeConvert==2.0.3
2 2
 Django==1.8.4
3 3
 MySQL-python==1.2.5
4
-TimeConvert==1.0.7
4
+TimeConvert==1.1.3
5 5
 django-multidomain==1.1.4
6 6
 django-shortuuidfield==0.1.3
7 7
 djangorestframework==3.3.1

+ 5 - 0
utils/ip_utils.py

@@ -0,0 +1,5 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+
4
+def ip_addr(request):
5
+    return request.META['HTTP_X_FORWARDED_FOR'] if 'HTTP_X_FORWARDED_FOR' in request.META else request.META['REMOTE_ADDR']

+ 0 - 2
utils/uuid_utils.py

@@ -2,8 +2,6 @@
2 2
 
3 3
 from django.conf import settings
4 4
 
5
-from photo.models import UUIDInfo
6
-
7 5
 import shortuuid
8 6
 
9 7